﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Geodatabase;
using MyGIS.Classes;
using MyGIS.Forms;
using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.DataSourcesRaster;
using ESRI.ArcGIS.SpatialAnalyst;
using ESRI.ArcGIS.GeoAnalyst;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Geoprocessor;
using ESRI.ArcGIS.SpatialAnalystTools;
using ESRI.ArcGIS.Geoprocessing;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Output;
using ESRI.ArcGIS.Display;

namespace MyGIS
{
    public sealed partial class Form1 : Form
    {
        private Pan mPan;
        private ZoomOut mZoomOut;
        private FixedZoomIn mFixedZoomIn;
        private FixedZoomOut mFixedZoomOut;
        private string mTool;//
        private ZoomIn mZoomIn;
        //空间查询的查询方式
        private int mQueryMode;
        //图层索引
        private int mLayerIndex;

        public Form1()
        {
            InitializeComponent();
            mPan = new Pan();
            mZoomIn = new ZoomIn();
            mZoomOut = new ZoomOut();
            mFixedZoomIn = new FixedZoomIn();
            mFixedZoomOut = new FixedZoomOut();

        }
        //
        public void UpdateDataGridView(DataTable data)
        {
            this.dataGridView1.DataSource = data;
            this.dataGridView1.Refresh();
        }
        //


        private void axMapControl1_OnMouseDown(object sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseDownEvent e)
        {

        }

        private void toolStripStatusLabel1_Click(object sender, EventArgs e)
        {

        }

        private void toolStripContainer1_ContentPanel_Load(object sender, EventArgs e)
        {

        }

        private void splitContainer2_Panel1_Paint(object sender, PaintEventArgs e)
        {

        }

        private void splitContainer2_Panel2_Paint(object sender, PaintEventArgs e)
        {

        }

        private void menuFileOpen_Click(object sender, EventArgs e)
        {
            //文件路径名称,包含文件名称和路径名称
            string strName = null;

            //定义OpenFileDialog，获取并打开地图文档
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Title = "打开MXD";
            openFileDialog.Filter = "MXD文件（*.mxd）|*.mxd";
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                strName = openFileDialog.FileName;
                if (strName != "")
                {
                    this.axMapControl1.LoadMxFile(strName);
                }
            }
            //地图文档全图显示
            this.axMapControl1.Extent = this.axMapControl1.FullExtent;
        }

        private void 添加数据ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ICommand cmd = new ControlsAddDataCommandClass();
            cmd.OnCreate(this.axMapControl1.Object);
            cmd.OnClick();
        }

        private void menuExit_Click(object sender, EventArgs e)
        {
            this.Dispose();
        }

        private void menuFullExtent_Click(object sender, EventArgs e)
        {
            //初始化FullExtent对象
            FullExtent fullExtent = new FullExtent();
            //FullExtent对象与MapControl关联
            fullExtent.OnCreate(this.axMapControl1.Object);
            fullExtent.OnClick();
        }

        private void menuZoomIn_Click(object sender, EventArgs e)
        {
            toolZoomIn_Click(sender, e);
        }
        private void menuZoomOut_Click(object sender, EventArgs e)
        {
            toolZoomOut_Click(sender, e);
        }
        private void menuFixedZoomIn_Click(object sender, EventArgs e)
        {
            toolFixedZoomIn_Click(sender, e);
        }

        private void menuFixedZoomOut_Click(object sender, EventArgs e)
        {
            toolFixedZoomOut_Click(sender, e);
        }
        private void menuPan_Click(object sender, EventArgs e)
        {
            //初始化Pan对象
            mPan = new Pan();
            //Pan对象与MapControl关联
            mPan.OnCreate(this.axMapControl1.Object);
            //设置鼠标形状
            this.axMapControl1.MousePointer = esriControlsMousePointer.esriPointerPan;
            //标记操作为“Pan”
            this.mTool = "Pan";
        }

        private void axTOCControl1_OnMouseDown(object sender, ITOCControlEvents_OnMouseDownEvent e)
        {

        }

        private void axMapControl1_OnMouseDown_1(object sender, IMapControlEvents2_OnMouseDownEvent e)
        {
            this.axMapControl1.Map.ClearSelection();
            //获取当前视图
            IActiveView pActiveView = this.axMapControl1.ActiveView;
            //获取鼠标点
            IPoint pPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y);
            switch (mTool)
            {
                case "ZoomIn":
                    this.mZoomIn.OnMouseDown(e.button, e.shift, e.x, e.y);
                    break;
                case "ZoomOut":
                    this.mZoomOut.OnMouseDown(e.button, e.shift, e.x, e.y);
                    break;
                case "Pan":
                    //设置鼠标形状
                    this.axMapControl1.MousePointer = esriControlsMousePointer.esriPointerPanning;
                    this.mPan.OnMouseDown(e.button, e.shift, e.x, e.y);
                    break;
                case "SpaceQuery":
                    IGeometry pGeometry = null;
                    if (this.mQueryMode == 0)//矩形查询
                    {
                        pGeometry = this.axMapControl1.TrackRectangle();
                    }
                    else if (this.mQueryMode == 1)//线查询
                    {
                        pGeometry = this.axMapControl1.TrackLine();
                    }
                    else if (this.mQueryMode == 2)//点查询
                    {
                        ITopologicalOperator pTopo;
                        IGeometry pBuffer;
                        pGeometry = pPoint;
                        pTopo = pGeometry as ITopologicalOperator;
                        //根据点位创建缓冲区，缓冲半径为0.1，可修改
                        pBuffer = pTopo.Buffer(0.1);
                        pGeometry = pBuffer.Envelope;
                    }
                    else if (this.mQueryMode == 3)//圆查询
                    {
                        pGeometry = this.axMapControl1.TrackCircle();
                    }
                    IFeatureLayer pFeatureLayer = this.axMapControl1.get_Layer(this.mLayerIndex) as IFeatureLayer;
                    DataTable pDataTable = this.LoadQueryResult(this.axMapControl1, pFeatureLayer, pGeometry);
                    this.dataGridView1.DataSource = pDataTable.DefaultView;

                    this.dataGridView1.Refresh();
                    break;
                default:
                    break;
            }
        }

        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void axMapControl1_OnMouseMove(object sender, IMapControlEvents2_OnMouseMoveEvent e)
        {
            switch (mTool)
            {
                case "ZoomIn":
                    this.mZoomIn.OnMouseMove(e.button, e.shift, e.x, e.y);
                    break;
                case "ZoomOut":
                    // 确保只传递鼠标移动事件给当前活动工具
                    if (this.axMapControl1.CurrentTool is ZoomOut)
                    {
                        this.mZoomOut.OnMouseMove(e.button, e.shift, e.x, e.y);
                    }
                    break;
                case "Pan":
                    this.mPan.OnMouseMove(e.button, e.shift, e.x, e.y);
                    break;
                default:
                    break;
            }
            // 显示当前比例尺
            this.StatusScale.Text = " 比例尺 1:"+((long)this.axMapControl1.MapScale).ToString();
            //// 显示当前坐标
            this.StatusCoordinate.Text = " 当前坐标 X = " + e.mapX.ToString() +  " Y = " +  e.mapY.ToString()  + " " +  this.axMapControl1.MapUnits;
            //this.statueCoordinate.Text = $" 当前坐标 X = {e.mapX} Y = {e.mapY} {this.axMapControl1.MapUnits}";

        }


        private void axMapControl1_OnMouseUp(object sender, IMapControlEvents2_OnMouseUpEvent e)
        {
            switch (mTool)
            {
                case "ZoomIn":
                    this.mZoomIn.OnMouseMove(e.button, e.shift, e.x, e.y);
                    break;
                case "ZoomOut":
                    this.mZoomOut.OnMouseMove(e.button, e.shift, e.x, e.y);
                    break;
                case "Pan":
                    this.mPan.OnMouseUp(e.button, e.shift, e.x, e.y);
                    //设置鼠标形状
                    this.axMapControl1.MousePointer = esriControlsMousePointer.esriPointerPan;
                    break;
                default:
                    break;
            }
        }

        private void menuAttributeQuery_Click(object sender, EventArgs e)
        {
            ////初始化属性查询窗体
            //AttributeQueryForm attributeQueryForm = new AttributeQueryForm(this.axMapControl1);
            //attributeQueryForm.Show();
            //初始化属性查询窗体
           using (AttributeQueryForm attributeQueryForm = new AttributeQueryForm(this.axMapControl1))
                {
                    attributeQueryForm.Owner = this;
                    attributeQueryForm.ShowDialog();
                }
        }
        private DataTable LoadQueryResult(AxMapControl mapControl, IFeatureLayer featureLayer, IGeometry geometry)
        {
            IFeatureClass pFeatureClass = featureLayer.FeatureClass;

            //根据图层属性字段初始化DataTable
            IFields pFields = pFeatureClass.Fields;
            DataTable pDataTable = new DataTable();
            for (int i = 0; i < pFields.FieldCount; i++)//i->i++
            {
                string strFldName;
                strFldName = pFields.get_Field(i).AliasName;
                pDataTable.Columns.Add(strFldName);
            }

            //空间过滤器
            ISpatialFilter pSpatialFilter = new SpatialFilter();
            pSpatialFilter.Geometry = geometry;

            //根据图层类型选择缓冲方式
            switch (pFeatureClass.ShapeType)
            {
                case esriGeometryType.esriGeometryPoint:
                    pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;
                    break;
                case esriGeometryType.esriGeometryPolyline:
                    pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelCrosses;
                    break;
                case esriGeometryType.esriGeometryPolygon:
                    pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
                    break;
            }
            //定义空间过滤器的空间字段
            pSpatialFilter.GeometryField = pFeatureClass.ShapeFieldName;

            IQueryFilter pQueryFilter;
            IFeatureCursor pFeatureCursor;
            IFeature pFeature;
            //利用要素过滤器查询要素
            pQueryFilter = pSpatialFilter as IQueryFilter;
            pFeatureCursor = featureLayer.Search(pQueryFilter, true);
            pFeature = pFeatureCursor.NextFeature();

            while (pFeature != null)
            {
                string strFldValue = null;
                DataRow dr = pDataTable.NewRow();
                //遍历图层属性表字段值，并加入pDataTable
                for (int i = 0; i < pFields.FieldCount; i++)//i->i++
                {
                    string strFldName = pFields.get_Field(i).Name;
                    if (strFldName == "Shape")
                    {
                        strFldValue = Convert.ToString(pFeature.Shape.GeometryType);
                    }
                    else
                        strFldValue = Convert.ToString(pFeature.get_Value(i));
                    dr[i] = strFldValue;
                }
                pDataTable.Rows.Add(dr);
                //高亮选择要素
                mapControl.Map.SelectFeature((ILayer)featureLayer, pFeature);
                mapControl.ActiveView.Refresh();
                pFeature = pFeatureCursor.NextFeature();
            }
            return pDataTable;
        }

        private void menuSpatialQuery_Click(object sender, EventArgs e)
        {
            //初始化空间查询窗体
            SpatialQueryForm spatialQueryForm = new SpatialQueryForm(this.axMapControl1);
            if (spatialQueryForm.ShowDialog() == DialogResult.OK)
            {
                //标记为“空间查询”
                this.mTool = "SpaceQuery";
                //获取查询方式和图层
                this.mQueryMode = spatialQueryForm.mQueryMode;
                this.mLayerIndex = spatialQueryForm.mLayerIndex;
                //定义鼠标形状
                this.axMapControl1.MousePointer = ESRI.ArcGIS.Controls.esriControlsMousePointer.esriPointerCrosshair;
            }
        }

        private void toolFullExtent_Click(object sender, EventArgs e)
        {
            //初始化FullExtent对象
            ICommand cmd = new ControlsMapFullExtentCommandClass();
            //FullExtent与MapControl的关联
            cmd.OnCreate(this.axMapControl1.Object);
            cmd.OnClick();
        }

        private void toolPan_Click(object sender, EventArgs e)
        {
            //初始化Pan对象
            ITool tool = new ControlsMapPanToolClass();
            //查询接口，初试化Command类型
            ICommand cmd = tool as ICommand;
            //Command与MapControl的关联
            cmd.OnCreate(this.axMapControl1.Object);
            cmd.OnClick();
            //当前MapControl的工具设为Pan
            this.axMapControl1.CurrentTool = tool;
        }
      
        private void UpdateToolbarIcons()
        {
            
            toolZoomIn.Checked = (mTool == "ZoomIn");
            toolZoomOut.Checked = (mTool == "ZoomOut");
            toolFixedZoomIn.Checked = (mTool == "FixedZoomIn");
            toolFixedZoomOut.Checked = (mTool == "FixedZoomOut");

        }
        private void toolZoomIn_Click(object sender, EventArgs e)
        {
            
            mZoomIn = new ZoomIn();
            mZoomIn.OnCreate(this.axMapControl1.Object);
            this.axMapControl1.CurrentTool = mZoomIn as ITool;
            this.mTool = "ZoomIn";
            UpdateToolbarIcons();
            this.axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair;
        }

        private void toolZoomOut_Click(object sender, EventArgs e)
        {
          
            mZoomOut = new ZoomOut();
            mZoomOut.OnCreate(this.axMapControl1.Object);
            this.axMapControl1.CurrentTool = mZoomOut as ITool;
            this.mTool = "ZoomOut";
            UpdateToolbarIcons();
            this.axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair;
        }
        private void toolFixedZoomIn_Click(object sender, EventArgs e)
        {
            mFixedZoomIn = new FixedZoomIn();
            mFixedZoomIn.OnCreate(this.axMapControl1.Object);
            this.axMapControl1.CurrentTool = null; // 固定缩放工具不需要设置CurrentTool
            mFixedZoomIn.OnClick();
            this.mTool = "FixedZoomIn";
            UpdateToolbarIcons();


        }

        private void toolFixedZoomOut_Click(object sender, EventArgs e)
        {
            mFixedZoomOut = new FixedZoomOut();
            mFixedZoomOut.OnCreate(this.axMapControl1.Object);
            this.axMapControl1.CurrentTool = null; // 固定缩放工具不需要设置CurrentTool
            mFixedZoomOut.OnClick();
            this.mTool = "FixedZoomOut";
            UpdateToolbarIcons();
        }

        private void menuBuffer_Click(object sender, EventArgs e)
        {
            BufferForm bufferForm = new BufferForm(this.axMapControl1.Object);
            if (bufferForm.ShowDialog() == DialogResult.OK)
            {
                //获取输出文件路径
                string strBufferPath = bufferForm.strOutputPath;
                //缓冲区图层载入到MapControl
                int index = strBufferPath.LastIndexOf("\\");
                this.axMapControl1.AddShapeFile(strBufferPath.Substring(0, index), strBufferPath.Substring(index));
            }
        }

        private void outputMenu_Click(object sender, EventArgs e)
        {
            int num = (int)Math.Round(this.axMapControl1.ActiveView.ScreenDisplay.DisplayTransformation.Resolution);

            CreateJPEGHiResolutionFromActiveView(this.axMapControl1.ActiveView, @"C:\Users\22311\Desktop\组件式开发\test.jpeg", 80);
            //ExportPDF();
            MessageBox.Show("完成");
        }
        public void CreateJPEGHiResolutionFromActiveView(IActiveView pActiveView, String pFileName, Int32 pOutputResolution)
        {
            ESRI.ArcGIS.Output.IExport pExport = new ESRI.ArcGIS.Output.ExportJPEGClass();//输出类型
            pExport.ExportFileName = pFileName;//输出路径
            pExport.Resolution = pOutputResolution;//输出分辨率

            tagRECT pExportRECT;//以像素为单位的图片大小
            pExportRECT.left = 0;
            pExportRECT.top = 0;
            pExportRECT.right = pActiveView.ExportFrame.right;//所见即所得，即控件大小；如果小于，那么相当于缩小，再导出
            pExportRECT.bottom = pActiveView.ExportFrame.bottom;//所见即所得，即控件大小；如果小于，那么相当于缩小，再导出

            //设备的坐标
            ESRI.ArcGIS.Geometry.IEnvelope pEnvelope = new ESRI.ArcGIS.Geometry.EnvelopeClass();
            pEnvelope.PutCoords(pExportRECT.left, pExportRECT.top, pExportRECT.right, pExportRECT.bottom);//采用PutCoords设置矩形
            pExport.PixelBounds = pEnvelope;//输出的像素范围

            System.Int32 hDC = pExport.StartExporting();//开始
            pActiveView.Output(hDC, (System.Int16)pExport.Resolution, ref pExportRECT, null, null);//输出
            pExport.FinishExporting();//结束
            pExport.Cleanup();//清除
        }

        private void ExportPDF(IActiveView pActiveView, String pFileName, Int32 pOutputResolution)
        {
            IExport pExport = new ExportPDFClass();//输出类型
            pExport.ExportFileName = pFileName;//输出路径
            pExport.Resolution = pOutputResolution;//输出分辨率

            tagRECT exportRECT;
            exportRECT.top = 0;
            exportRECT.left = 0;
            exportRECT.right = pActiveView.ExportFrame.right;
            exportRECT.bottom = pActiveView.ExportFrame.bottom;

            IEnvelope pPixelBoundsEnv = new EnvelopeClass();
            pPixelBoundsEnv.PutCoords(exportRECT.left, exportRECT.bottom, exportRECT.right, exportRECT.top);
            pExport.PixelBounds = pPixelBoundsEnv;

            int hDC = pExport.StartExporting();
            pActiveView.Output(hDC, (int)pExport.Resolution, ref exportRECT, null, null);
            pExport.FinishExporting();
            pExport.Cleanup();
        }

        private void menuKernelDensity_Click(object sender, EventArgs e)
        {
            //获取数据将其转成 IGeoDataset，指定相应的字段
            IFeatureLayer pFeatlyr = this.axMapControl1.get_Layer(0) as IFeatureLayer;
            IFeatureClass featureClass = pFeatlyr.FeatureClass;
            IFeatureClassDescriptor featureDes = new FeatureClassDescriptorClass();
            featureDes.Create(featureClass, null, "POPU");
            IGeoDataset inGeoDataset = featureDes as IGeoDataset;

            IRasterAnalysisEnvironment rasterEnv = new RasterDensityOpClass(); ;//环境分析对象,与点要素的范围一致
            //object extentProviderObj = pFeatlyr;
            //rasterEnv.SetExtent(esriRasterEnvSettingEnum.esriRasterEnvValue, ref extentProviderObj);

            object cellSizeObj = 50;
            rasterEnv.SetCellSize(esriRasterEnvSettingEnum.esriRasterEnvValue, ref cellSizeObj);

            //核密度分析方法
            object radioDisObj = 600;
            IDensityOp densityOp = (IDensityOp)rasterEnv;
            IGeoDataset outGeoDataset = densityOp.KernelDensity(inGeoDataset, ref radioDisObj, null);

            // 4. 显示结果
            IRasterLayer rasterLayer = new RasterLayerClass();
            rasterLayer.CreateFromDataset(outGeoDataset as IRasterDataset);
            rasterLayer.Name = "KernelDensity";
            axMapControl1.AddLayer(rasterLayer);
            axMapControl1.ActiveView.Refresh();
        }

        private void 统计图表ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //获取目标图层
            ILayer pLayer = axMapControl1.get_Layer(2);
            if (pLayer == null)
            {
                MessageBox.Show("无法获取指定索引的图层", "图层错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            IFeatureLayer pGeoFeatLyr = pLayer as IFeatureLayer;
            if (pGeoFeatLyr == null)
            {
                MessageBox.Show("所选图层不是要素图层", "图层类型错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            Dictionary<string, IRgbColor> _dicFieldAndColor = null;
            _dicFieldAndColor = new Dictionary<string, IRgbColor>();
            _dicFieldAndColor.Add("aqi", GetRgbColor(0, 0, 255));
            _dicFieldAndColor.Add("pm25", GetRgbColor(0, 255, 0));

            ChartRenderer(axMapControl1, axTOCControl1, pGeoFeatLyr, _dicFieldAndColor);
        }

        private IRgbColor GetRgbColor(int red, int green, int blue)
        {
            IRgbColor rgbColor = new RgbColorClass();
            rgbColor.Red = red;
            rgbColor.Green = green;
            rgbColor.Blue = blue;
            return rgbColor;
        }

        private void ChartRenderer(AxMapControl myMapcontrol, AxTOCControl myTOCcontrol, IFeatureLayer pFeatLyr, Dictionary<string, IRgbColor> dicFieldAndColor)
        {
            IGeoFeatureLayer pGeoFeatLyr = pFeatLyr as IGeoFeatureLayer;
            IChartRenderer pChartRender = new ChartRendererClass();
            IRendererFields pRenderFields = pChartRender as IRendererFields;

            //1.1.1条形符号
            IBarChartSymbol pBarChartSym = null;
            pBarChartSym = new BarChartSymbolClass();
            pBarChartSym.Width = 6;//设置每个条形图的宽度

            //1.1.2.1遍历出所选择的第一个字段的最大值，作为设置专题图的比例大小的依据
            double dMax = 0; double dTemp = 0; IDataStatistics pDataSta = null; IFeatureCursor pCursor = pGeoFeatLyr.Search(null, true);
            foreach (KeyValuePair<string, IRgbColor> _keyValue in dicFieldAndColor)
            {
                pRenderFields.AddField(_keyValue.Key, _keyValue.Key);
                pDataSta = new DataStatisticsClass();
                pDataSta.Cursor = pCursor as ICursor;
                pDataSta.Field = _keyValue.Key;
                dTemp = pDataSta.Statistics.Maximum;
                if (dTemp >= dMax)
                {
                    dMax = dTemp;
                }
            }

            //1.1.2 转换接口的设置1，设置最大值与高度
            IChartSymbol pChartSym = pBarChartSym as IChartSymbol;
            pChartSym.MaxValue = dMax;
            IMarkerSymbol pMarkerSym = pBarChartSym as IMarkerSymbol;
            pMarkerSym.Size = 30;//设置条形图的高度

            //1.1.3 转换接口的设置2 增加 多个符号样式
            ISymbolArray pSymArray = pBarChartSym as ISymbolArray;
            IFillSymbol pFillSymbol = null;
            foreach (KeyValuePair<string, IRgbColor> _keyValue in dicFieldAndColor)
            {
                //获取渲染字段的颜色值
                IRgbColor pRgbColor = _keyValue.Value;
                pFillSymbol = new SimpleFillSymbolClass();
                pFillSymbol.Color = pRgbColor as IColor;
                pSymArray.AddSymbol(pFillSymbol as ISymbol);
            }

            //1.1图形渲染器的符号样式设置
            pChartRender.ChartSymbol = pBarChartSym as IChartSymbol;

            //1.2图形渲染器的背景设置
            pFillSymbol = new SimpleFillSymbolClass();
            pFillSymbol.Color = GetRgbColor(239, 228, 190);
            pChartRender.BaseSymbol = pFillSymbol as ISymbol;// 设置背景符号

            //1.3生成图例
            pChartRender.CreateLegend();

            //1设置图层渲染器
            pGeoFeatLyr.Renderer = pChartRender as IFeatureRenderer;
            myMapcontrol.Refresh();
            myTOCcontrol.Update();

        }
    }
}
